@@ -1,107 +0,0 @@ |
||
1 |
-require 'forecast_io' |
|
2 |
-require 'date' |
|
3 |
- |
|
4 |
-module Agents |
|
5 |
- class ForecastAgent < Agent |
|
6 |
- cannot_receive_events! |
|
7 |
- |
|
8 |
- description <<-MD |
|
9 |
- The ForecastAgent creates an event for the following day's weather at a given `latitude` and `longitude`. |
|
10 |
- |
|
11 |
- You also must select which `day` you would like to get the weather for where the number 0 is for today and 1 is for tomorrow and so on. Weather is only returned for 1 week at a time. |
|
12 |
- |
|
13 |
- You must setup an [API key for Forecast](https://developer.forecast.io/) in order to use this Agent. |
|
14 |
- MD |
|
15 |
- |
|
16 |
- event_description <<-MD |
|
17 |
- Events look like this: |
|
18 |
- |
|
19 |
- { |
|
20 |
- "time" : 1391320800, |
|
21 |
- "summary" : "Rain throughout the day.", |
|
22 |
- "icon" : "rain", |
|
23 |
- "sunriseTime" : "06:48", |
|
24 |
- "sunsetTime" : "17:16", |
|
25 |
- "moonPhase" : 0.11, |
|
26 |
- "precipIntensity" : 0.0582, |
|
27 |
- "precipIntensityMax" : 0.1705, |
|
28 |
- "precipIntensityMaxTime" : "21:00", |
|
29 |
- "precipProbability" : 1, |
|
30 |
- "precipType" : "rain", |
|
31 |
- "temperatureMin" : 35.67, |
|
32 |
- "temperatureMinTime" : "23:00", |
|
33 |
- "temperatureMax" : 50.82, |
|
34 |
- "temperatureMaxTime" : "02:00", |
|
35 |
- "apparentTemperatureMin" : 26.11, |
|
36 |
- "apparentTemperatureMinTime" : "23:00", |
|
37 |
- "apparentTemperatureMax" : 50.82, |
|
38 |
- "apparentTemperatureMaxTime" : "02:00", |
|
39 |
- "dewPoint" : 41, |
|
40 |
- "humidity" : 0.92, |
|
41 |
- "windSpeed" : 4.59, |
|
42 |
- "windBearing" : 358, |
|
43 |
- "visibility" : 5.92, |
|
44 |
- "cloudCover" : 0.99, |
|
45 |
- "pressure" : 1017.66, |
|
46 |
- "ozone" : 278.6 |
|
47 |
- } |
|
48 |
- |
|
49 |
- MD |
|
50 |
- |
|
51 |
- default_schedule "8pm" |
|
52 |
- |
|
53 |
- def working? |
|
54 |
- event_created_within?(2) && !recent_error_logs? |
|
55 |
- end |
|
56 |
- |
|
57 |
- def key_setup? |
|
58 |
- options['api_key'] && options['api_key'] != "your-key" |
|
59 |
- end |
|
60 |
- |
|
61 |
- def default_options |
|
62 |
- { |
|
63 |
- 'api_key' => "your-key", |
|
64 |
- 'latitude' => "36.166667", |
|
65 |
- 'longitude' => "-86.783333", |
|
66 |
- 'day' => "0" |
|
67 |
- } |
|
68 |
- end |
|
69 |
- |
|
70 |
- def validate_options |
|
71 |
- errors.add(:base, "latitude is required") unless options['latitude'].present? |
|
72 |
- errors.add(:base, "longitude is required") unless options['longitude'].present? |
|
73 |
- errors.add(:base, "api_key is required") unless options['api_key'].present? |
|
74 |
- errors.add(:base, "day selection is required") unless options['day'].present? |
|
75 |
- end |
|
76 |
- |
|
77 |
- def check |
|
78 |
- if key_setup? |
|
79 |
- ForecastIO.api_key = options['api_key'] |
|
80 |
- ForecastIO.forecast(options['latitude'],options['longitude']).daily.each do |key, value| |
|
81 |
- if key == "data" |
|
82 |
- value.each do |day| |
|
83 |
- if day_diff(day.time) == options['day'].tp_i |
|
84 |
- day.sunriseTime = Time.at(day.sunriseTime).strftime("%H:%M") |
|
85 |
- day.sunsetTime = Time.at(day.sunsetTime).strftime("%H:%M") |
|
86 |
- day.precipIntensityMaxTime = Time.at(day.precipIntensityMaxTime).strftime("%H:%M") |
|
87 |
- day.temperatureMinTime = Time.at(day.temperatureMinTime).strftime("%H:%M") |
|
88 |
- day.temperatureMaxTime = Time.at(day.temperatureMaxTime).strftime("%H:%M") |
|
89 |
- day.apparentTemperatureMinTime = Time.at(day.apparentTemperatureMinTime).strftime("%H:%M") |
|
90 |
- day.apparentTemperatureMaxTime = Time.at(day.apparentTemperatureMaxTime).strftime("%H:%M") |
|
91 |
- create_event :payload => day |
|
92 |
- end |
|
93 |
- end |
|
94 |
- end |
|
95 |
- end |
|
96 |
- end |
|
97 |
- end |
|
98 |
- |
|
99 |
- def day_diff(day) |
|
100 |
- a=Time.at(day).to_date |
|
101 |
- b=Time.now.to_date |
|
102 |
- days=(a-b).to_i |
|
103 |
- return days |
|
104 |
- end |
|
105 |
- |
|
106 |
- end |
|
107 |
-end |
@@ -6,11 +6,19 @@ module Agents |
||
6 | 6 |
cannot_receive_events! |
7 | 7 |
|
8 | 8 |
description <<-MD |
9 |
- The WeatherAgent creates an event for the following day's weather at a given `location`. |
|
9 |
+ The WeatherAgent creates an event for the day's weather at a given `location`. |
|
10 | 10 |
|
11 |
- The `location` can be a US zipcode, or any location that Wunderground supports. To find one, search [wunderground.com](http://wunderground.com) and copy the location part of the URL. For example, a result for San Francisco gives `http://www.wunderground.com/US/CA/San_Francisco.html` and London, England gives `http://www.wunderground.com/q/zmw:00000.1.03772`. The locations in each are `US/CA/San_Francisco` and `zmw:00000.1.03772`, respectively. |
|
11 |
+ You also must select `which_day` you would like to get the weather for where the number 0 is for today and 1 is for tomorrow and so on. Weather is only returned for 1 week at a time. |
|
12 | 12 |
|
13 |
- You must setup an [API key for Wunderground](http://www.wunderground.com/weather/api/) in order to use this Agent. |
|
13 |
+ The weather can be provided by either Wunderground or ForecastIO. To choose which `service` to use, enter either `forecastio` or `wunderground`. |
|
14 |
+ |
|
15 |
+ The `location` can be a US zipcode, or any location that Wunderground supports. To find one, search [wunderground.com](http://wunderground.com) and copy the location part of the URL. For example, a result for San Francisco gives `http://www.wunderground.com/US/CA/San_Francisco.html` and London, England gives `http://www.wunderground.com/q/zmw:00000.1.03772`. The locations in each are `US/CA/San_Francisco` and `zmw:00000.1.03772`, respectively. |
|
16 |
+ |
|
17 |
+ If you plan on using ForecastIO, the `location` must be a set of GPS coordinates. |
|
18 |
+ |
|
19 |
+ You must setup an [API key for Wunderground](http://www.wunderground.com/weather/api/) in order to use this Agent with Wunderground. |
|
20 |
+ |
|
21 |
+ You must setup an [API key for Forecast](https://developer.forecast.io/) in order to use this Agent with ForecastIO. |
|
14 | 22 |
MD |
15 | 23 |
|
16 | 24 |
event_description <<-MD |
@@ -44,38 +52,120 @@ module Agents |
||
44 | 52 |
event_created_within?(2) && !recent_error_logs? |
45 | 53 |
end |
46 | 54 |
|
47 |
- def wunderground |
|
48 |
- Wunderground.new(options['api_key']) if key_setup? |
|
49 |
- end |
|
50 |
- |
|
51 | 55 |
def key_setup? |
52 | 56 |
options['api_key'] && options['api_key'] != "your-key" |
53 | 57 |
end |
54 | 58 |
|
55 | 59 |
def default_options |
56 | 60 |
{ |
57 |
- 'api_key' => "your-key", |
|
58 |
- 'location' => "94103" |
|
61 |
+ 'service' => 'wunderground', |
|
62 |
+ 'api_key' => 'your-key', |
|
63 |
+ 'location' => '94103', |
|
64 |
+ 'which_day' => '0' |
|
59 | 65 |
} |
60 | 66 |
end |
61 | 67 |
|
62 | 68 |
def validate_options |
63 |
- errors.add(:base, "location is required") unless options['location'].present? || options['zipcode'].present? |
|
69 |
+ errors.add(:base, "service is required") unless options['service'].present? |
|
70 |
+ errors.add(:base, "service must be set to 'forecastio' or 'wunderground'") unless ["forecastio", "wunderground"].include?(options['service']) |
|
71 |
+ errors.add(:base, "location is required") unless options['location'].present? |
|
64 | 72 |
errors.add(:base, "api_key is required") unless options['api_key'].present? |
73 |
+ errors.add(:base, "which_day selection is required") unless options['which_day'].present? |
|
74 |
+ end |
|
75 |
+ |
|
76 |
+ def wunderground |
|
77 |
+ data = Wunderground.new(options['api_key']).forecast_for(options['location'])['forecast']['simpleforecast']['forecastday'] if key_setup? |
|
78 |
+ return data |
|
79 |
+ end |
|
80 |
+ |
|
81 |
+ def forecastio |
|
82 |
+ ForecastIO.api_key = options['api_key'] if key_setup? |
|
83 |
+ data = ForecastIO.forecast(options['location'].split(',')[0],options['location'].split(',')[1])['daily']['data'] |
|
84 |
+ return data |
|
85 |
+ end |
|
86 |
+ |
|
87 |
+ def model(data,service,which_day) |
|
88 |
+ day = Hash.new |
|
89 |
+ if service == "wunderground" |
|
90 |
+ day = data[which_day.to_i] |
|
91 |
+ elsif service == "forecastio" |
|
92 |
+ data.each do |value| |
|
93 |
+ timestamp = Time.at(value.time) |
|
94 |
+ if (timestamp.to_date - Time.now.to_date).to_i == which_day.to_i |
|
95 |
+ day = { |
|
96 |
+ 'date' => { |
|
97 |
+ 'epoch' => value.time.to_s, |
|
98 |
+ 'pretty' => timestamp.strftime("%l:%M %p %Z on %B %d, %Y"), |
|
99 |
+ 'day' => timestamp.day, |
|
100 |
+ 'month' => timestamp.month, |
|
101 |
+ 'year' => timestamp.year, |
|
102 |
+ 'yday' => timestamp.yday, |
|
103 |
+ 'hour' => timestamp.hour, |
|
104 |
+ 'min' => timestamp.strftime("%M"), |
|
105 |
+ 'sec' => timestamp.sec, |
|
106 |
+ 'isdst' => timestamp.isdst ? 1 : 0 , |
|
107 |
+ 'monthname' => timestamp.strftime("%B"), |
|
108 |
+ 'monthname_short' => timestamp.strftime("%b"), |
|
109 |
+ 'weekday_short' => timestamp.strftime("%a"), |
|
110 |
+ 'weekday' => timestamp.strftime("%A"), |
|
111 |
+ 'ampm' => timestamp.strftime("%p"), |
|
112 |
+ 'tz_short' => timestamp.zone |
|
113 |
+ }, |
|
114 |
+ 'period' => which_day.to_i, |
|
115 |
+ 'high' => { |
|
116 |
+ 'fahrenheit' => value.temperatureMax.round().to_s, |
|
117 |
+ 'epoch' => value.temperatureMaxTime.to_s, |
|
118 |
+ 'fahrenheit_apparent' => value.apparentTemperatureMax.round().to_s, |
|
119 |
+ 'epoch_apparent' => value.apparentTemperatureMaxTime.to_s, |
|
120 |
+ 'celsius' => ((5*(Float(value.temperatureMax) - 32))/9).round().to_s |
|
121 |
+ }, |
|
122 |
+ 'low' => { |
|
123 |
+ 'fahrenheit' => value.temperatureMin.round().to_s, |
|
124 |
+ 'epoch' => value.temperatureMinTime.to_s, |
|
125 |
+ 'fahrenheit_apparent' => value.apparentTemperatureMin.round().to_s, |
|
126 |
+ 'epoch_apparent' => value.apparentTemperatureMinTime.to_s, |
|
127 |
+ 'celsius' => ((5*(Float(value.temperatureMin) - 32))/9).round().to_s |
|
128 |
+ }, |
|
129 |
+ 'conditions' => value.summary, |
|
130 |
+ 'icon' => value.icon, |
|
131 |
+ 'avehumidity' => (value.humidity * 100).to_i, |
|
132 |
+ 'sunriseTime' => value.sunriseTime.to_s, |
|
133 |
+ 'sunsetTime' => value.sunsetTime.to_s, |
|
134 |
+ 'moonPhase' => value.moonPhase.to_s, |
|
135 |
+ 'precip' => { |
|
136 |
+ 'intensity' => value.precipIntensity.to_s, |
|
137 |
+ 'intensity_max' => value.precipIntensityMax.to_s, |
|
138 |
+ 'intensity_max_epoch' => value.precipIntensityMaxTime.to_s, |
|
139 |
+ 'probability' => value.precipProbability.to_s, |
|
140 |
+ 'type' => value.precipType |
|
141 |
+ }, |
|
142 |
+ 'dewPoint' => value.dewPoint.to_s, |
|
143 |
+ 'avewind' => { |
|
144 |
+ 'mph' => value.windSpeed.round().to_s, |
|
145 |
+ 'kph' => (Float(value.windSpeed) * 1.609344).round().to_s, |
|
146 |
+ 'degrees' => value.windBearing.to_s |
|
147 |
+ }, |
|
148 |
+ 'visibility' => value.visibility.to_s, |
|
149 |
+ 'cloudCover' => value.cloudCover.to_s, |
|
150 |
+ 'pressure' => value.pressure.to_s, |
|
151 |
+ 'ozone' => value.ozone.to_s |
|
152 |
+ } |
|
153 |
+ end |
|
154 |
+ end |
|
155 |
+ end |
|
156 |
+ return day.merge('location' => options['location']) |
|
65 | 157 |
end |
66 | 158 |
|
67 | 159 |
def check |
68 | 160 |
if key_setup? |
69 |
- wunderground.forecast_for(options['location'] || options['zipcode'])["forecast"]["simpleforecast"]["forecastday"].each do |day| |
|
70 |
- if is_tomorrow?(day) |
|
71 |
- create_event :payload => day.merge('location' => options['location'] || options['zipcode']) |
|
72 |
- end |
|
161 |
+ if options['service'] == 'forecastio' |
|
162 |
+ weather = model(forecastio,options['service'],options['which_day']) |
|
163 |
+ elsif options['service'] == 'wunderground' |
|
164 |
+ weather = model(wunderground,options['service'],options['which_day']) |
|
73 | 165 |
end |
166 |
+ create_event :payload => weather |
|
74 | 167 |
end |
75 | 168 |
end |
76 | 169 |
|
77 |
- def is_tomorrow?(day) |
|
78 |
- Time.zone.at(day["date"]["epoch"].to_i).to_date == Time.zone.now.tomorrow.to_date |
|
79 |
- end |
|
80 | 170 |
end |
81 | 171 |
end |